package com.daylightrobbery.server;

import com.daylightrobbery.entity.Account;
import com.daylightrobbery.server.entity.PlayerInfo;
import com.daylightrobbery.server.entity.Room;
import com.daylightrobbery.server.packet.PlayerInGame;
import com.daylightrobbery.server.packet.game.player.PlayerInfoSyncPacket;
import com.daylightrobbery.service.AccountService;
import com.daylightrobbery.service.UserSignInLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

@Component
public class GameManager {
    private static final GameManager instance = new GameManager();
    private ConcurrentHashMap<String, Account> allOnlineUser;
    private ConcurrentHashMap<Integer, Room> roomMap;
    private ConcurrentHashMap<String, InetSocketAddress>  uidToRecipientMap;
    private ConcurrentHashMap<String, PlayerInGame> inGameMap;
    private ConcurrentHashMap<Integer, List<String>> playerUidRoundOrder;
    private ScheduledExecutorService checkRoomStatus;

    public static GameManager Instance;

    @Autowired
    public AccountService accountService;
    @Autowired
    public UserSignInLogService userSignInLogService;

    private GameManager() {
        allOnlineUser = new ConcurrentHashMap<>();
        roomMap = new ConcurrentHashMap<>();
        uidToRecipientMap = new ConcurrentHashMap<>();
        checkRoomStatus = Executors.newSingleThreadScheduledExecutor();
        playerUidRoundOrder = new ConcurrentHashMap<>();
        inGameMap = new ConcurrentHashMap<>();
        Instance = this;
    }

    public Room createRoom(String uid){
        PlayerInfo playerInfo = new PlayerInfo()
                .setUid(uid)
                .setAccount(allOnlineUser.get(uid).getAccount());
        Room room = new Room()
                .setRoomOwnerUid(uid)
                .setRoomName("[" + playerInfo.getAccount() + "]的房间")
                .addPlayers(playerInfo);
        roomMap.put(room.getRoomId(), room);
        List<String> list = this.playerUidRoundOrder.computeIfAbsent(room.getRoomId(), k -> new ArrayList<>());
        list.add(uid);
        return room;
    }

    public Room addPlayerToRoom(String uid, Integer roomId){
        Room room = roomMap.get(roomId);
        PlayerInfo playerInfo = new PlayerInfo()
                .setUid(uid)
                .setAccount(allOnlineUser.get(uid).getAccount());
        room.getPlayers().put(uid, playerInfo);
        List<String> list = this.playerUidRoundOrder.get(roomId);
        list.add(uid);
        return room;
    }

    public Room removePlayerToRoom(String uid, Integer roomId){
        Room room = roomMap.get(roomId);
        // 是房主自己退出
        if(uid.equals(room.getRoomOwnerUid())){
            return room.setRoomOwnerUid(null);
        }
        room.getPlayers().remove(uid);
        List<String> list = this.playerUidRoundOrder.get(roomId);
        list.remove(uid);
        return room;
    }

    public void removeRoom(int roomId){
        this.roomMap.remove(roomId);
    }


    public void addUserOnline(String uid, Account account){
        this.allOnlineUser.put(uid, account);
    }

    public void recordUserAddress(String uid, InetSocketAddress address){
        this.uidToRecipientMap.put(uid, address);
    }

    public InetSocketAddress getUserAddress(String uid){
        return this.uidToRecipientMap.get(uid);
    }


    public List<Room> getRoomList(){
        return new ArrayList<>(roomMap.values());
    }

    public List<String> getPlayerUidRoundOrder(Integer roomId){
        return this.playerUidRoundOrder.get(roomId);
    }

    public  Room getRoomById(Integer roomId){
        return this.roomMap.get(roomId);
    }

    public static GameManager getInstance() {
        return instance;
    }

    public void addPlayerInGame(String uid, Integer roomId){
        inGameMap.put(uid, new PlayerInGame().setUid(uid).setRoomId(roomId));
    }

    public PlayerInGame getPlayerInGame(String uid){
        return inGameMap.get(uid);
    }
    public void removePlayerInGame(String uid){
        this.inGameMap.remove(uid);
    }

    public Integer getPlayerInGameRoomId(String uid){
        PlayerInGame playerInGame = inGameMap.get(uid);
        if (playerInGame != null) {
            return playerInGame.getRoomId();
        }else{
            return null;
        }
    }


    public List<PlayerInfoSyncPacket> getAllPlayerSyncPackets(Integer roomId){
        Room room = roomMap.get(roomId);
        if (room == null) {
            return null;
        }
        ConcurrentHashMap<String, PlayerInfo> players = room.getPlayers();
        List<PlayerInfoSyncPacket> list = new LinkedList<>();
        for (Map.Entry<String, PlayerInfo> entry : players.entrySet()) {
            list.add(this.inGameMap.get(entry.getKey()).getPacket());
        }
        return list;
    }


}
